package rbb.itm5.bwinf.roboter.Control;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import rbb.itm5.bwinf.roboter.ClassFinder;
import rbb.itm5.bwinf.roboter.Control.Drivers.SampleDriver;
import rbb.itm5.bwinf.roboter.Model.Room;
import rbb.itm5.bwinf.roboter.View.Gui;

/**
 * Diese Klasse erstellt alle Objekte und Referenzen.
 *
 * @author Dominik Jakielski
 *
 */
public class Controler {

    private Gui view;
    private Room room;
    private ControlerEvents event;
    private ArrayList<DriverInterface> drivers=new ArrayList<DriverInterface>();
    private int driverIndex;

    public Controler() {
        event = new ControlerEvents(this);
        view = new Gui(event);
        room = new Room(event);
        room.loadRoom("maps/raum0_beispiel.txt");
        inflateGui();
        loadModel();
    }
    //Erstelle die GUI

    private void inflateGui() {
        if (room.getSize().width > 0 && room.getSize().height > 0) {
            view.initGui(room.getSize().width, room.getSize().height);
        } else {
            view.initGui(20, 20);
        }
        view.buildGui();
    }

    /**
     * Startet das Programm mit der View
     */
    public void start() {
        view.start();
    }

    //Zugriffs Methoden für weitere Controler
    /**
     * Gibt das Raum-Model Objekt zurück
     */
    Room getRoom() {
        return room;
    }

    /**
     * Gibt das View-Objekt zurück.
     *
     * @return View-Objekt
     */
    Gui getView() {
        return view;
    }

    /**
     * Gibt das Roboter-Model Objekt zurück
     */
    Roboter getRoboter() {
        return room.getRoboter();
    }

    public void setDriver(DriverInterface driver) {
        if (driver != null && driver instanceof DriverInterface && drivers.contains(driver)) {
            driverIndex=drivers.indexOf(driver);
            view.getControlPanel().refreshModel();
        }
    }

    public DriverInterface getDriver() {
        return drivers.get(driverIndex);
    }
    
    public DriverInterface getDriver(Class driver) {
        DriverInterface re=null;
        for (DriverInterface d : drivers) {
            if(d.getClass().equals(driver)){
                re=d;
                break;
            }
        }
        return re;
    }
    
    public DriverInterface getDriver(String Driver) {
        DriverInterface re=null;
        for (DriverInterface d : drivers) {
            if(d.getName().equalsIgnoreCase(Driver)){
                re=d;
                break;
            }
        }
        return re;
    }

    public ArrayList<DriverInterface> getDrivers() {
        return drivers;
    }
    
    

    public DriverInterface createDriver(Class c) {
        DriverInterface driver = null;
        if (c.getSuperclass().equals(DriverInterface.class)) {
            try {
                Constructor constructor = c.getConstructor(new Class[]{Roboter.class});
                try {
                    driver = (DriverInterface) constructor.newInstance(getRoboter());
                } catch (InstantiationException ex) {
                    Logger.getLogger(Controler.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    Logger.getLogger(Controler.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalArgumentException ex) {
                    Logger.getLogger(Controler.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(Controler.class.getName()).log(Level.SEVERE, null, ex);
                }
            } catch (NoSuchMethodException ex) {
                Logger.getLogger(Controler.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(Controler.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return driver;

    }

    private void loadModel() {
        event.loadRoomBox();
        
        
        List<Class<?>> classes = ClassFinder.getClasses("rbb.itm5.bwinf.roboter.Control.Drivers", DriverInterface.class);
        for (Class<?> DriverClases : classes) {
            drivers.add(createDriver(DriverClases));
        }
        setDriver(getDriver(SampleDriver.class));
        
        getView().getControlPanel().setDriverBoxModel(new DefaultComboBoxModel(drivers.toArray()));
        getView().getControlPanel().setDriver(getDriver());
    }
    
    public void addDriver(Class Driver){
        drivers.add(createDriver(Driver));
    }
    public void addDrivers(Class[] Drivers){
        for (Class d : Drivers) {
            drivers.add(createDriver(d));
        }        
    }

    public void addDrivers(List<Class<?>> Drivers) {
        for (Class d : Drivers) {
            drivers.add(createDriver(d));
        }  
    }
}
